iT邦幫忙

2024 iThome 鐵人賽

DAY 30
0
Security

picoCTF系列 第 30

[Day 30] Classic Crackme 0x100

  • 分享至 

  • xImage
  •  

來到最後一天了!以我最感興趣的反向工程作為結尾!

題目希望我們破解本地的 binary file ,並以這組 password 連上 server,並且提示告訴我們使用機器去解決符號。
https://ithelp.ithome.com.tw/upload/images/20240922/20168342oEbgenR1R1.png
hint 1:Let the machine figure out the symbols!

下載題目給的 elf 檔案,並且試著連上 webshell,會發現要輸入密碼。

$ ls -l 
-rw-rw-r--  1 peggggy-picoctf peggggy-picoctf   19112 Mar 12 00:36 crackme100
$ nc titan.picoctf.net 51974
Enter the secret password: 
1
FAILED!

題目的提示告訴我們,讓機器去解決符號,於是我上網 google,發現方法不外乎是使用:

(1) IDA ( 靜態分析 )、(2) GDB ( 動態分析 )、(3) 自動分析 ( 詳情可參閱:Binary 自動分析的那些事 )

靜態分析重在程式結構和潛在問題的靜態檢查,代表工具如 IDA。動態分析重在程式運行時的行為監控和問題發現,代表工具如 GDB。自動分析結合上述兩種技術,利用自動化工具進行程式分析。

這裡我想採用自動分析,於是我又去查了 angr 這個套件怎麼使用 ( 參閱:Simulation Managersangr初探 ),然後知道要使用 simgr.explore( find , avoid ),所以要知道想要跳到 ( find ) 的地址 ,以及想要避免 ( avoid ) 的地址。
https://ithelp.ithome.com.tw/upload/images/20240922/20168342WRCjnFxQQm.png

因此,使用 Ghidra ( 詳情請見: 必備!好用的逆向分析工具Ghidra入門介紹 ) 分析得到的 elf 檔案,並且可以看到 “Success!........” 在 0x00401378 的位置,”FAILED!” 在 0x00401389 的位置。
https://ithelp.ithome.com.tw/upload/images/20240922/201683425tvoFZT5LV.png

於是我們可以寫出以下的檔案,並且執行。執行後會得到一串 binary 的字串 ( 只是要跑有點久 )。

#!/usr/bin/env python3

import angr

def main():
	proj = angr.Project("crackme100")
	state = proj.factory.entry_state()
	simgr = proj.factory.simgr(state)
	simgr.explore(find=0x00401378, avoid=0x00401389)

	return simgr.found[0].posix.dumps(0)

if __name__ == '__main__':
	print(main())
$ python3 script.py 
WARNING | 2024-08-05 00:19:50,922 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory with an unspecified value. This could indicate unwanted behavior.
WARNING | 2024-08-05 00:19:50,923 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2024-08-05 00:19:50,923 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2024-08-05 00:19:50,923 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2024-08-05 00:19:50,923 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2024-08-05 00:19:50,923 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fffffffffeff8c with 4 unconstrained bytes referenced from 0x401095 (_start+0x5 in crackme100 (0x401095))
WARNING | 2024-08-05 00:19:51,221 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fffffffffeff33 with 41 unconstrained bytes referenced from 0x59dc90 (strlen+0x0 in libc.so.6 (0x9dc90))
WARNING | 2024-08-05 00:19:51,221 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fffffffffeff70 with 8 unconstrained bytes referenced from 0x59dc90 (strlen+0x0 in libc.so.6 (0x9dc90))
b'zqncqnqkun}\\s)igianqoofjf]ub\xd7fgyilppb_j\xbcroi\xf2fl|A\\}'

再使用 pwntool,連上 webshell,並且傳送剛剛所得到字串。

#!/usr/bin/env python3

from pwn import *

context.log_level='critical'
p = remote("titan.picoctf.net", 51974)

p.recvuntil(b"Enter the secret password: ")

p.sendline(b"zqncqnqkun}\\s)igianqoofjf]ub\xd7fgyilppb_j\xbcroi\xf2fl|A\\}")

print(p.recvall())

接著就可以得到 flag 了!

$ python3 pwnscript.py 
b'SUCCESS! Here is your flag: picoCTF{s0lv3_angry_symb0ls_4656b68e}\n'

當然,若是不想使用 angr 自動分析,也可以使用 Ghidra 得到 decompile 的 code ( 以下是 decompile 後完整的 code ),再人工轉換成 python script,或是使用 z3 ( 詳閱:Z3 API in Python,但這個我不太會寫就不提供 code 了)。

undefined8 main(void)

{
  int iVar1;
  size_t sVar2;
  char local_a8 [64];
  undefined8 local_68;
  undefined8 local_60;
  undefined8 local_58;
  undefined8 local_50;
  undefined8 local_48;
  undefined7 local_40;
  undefined4 uStack57;
  uint local_2c;
  uint local_28;
  char local_21;
  uint local_20;
  uint local_1c;
  uint local_18;
  int local_14;
  int local_10;
  int local_c;
  
  local_68 = 0x747774746971747a;
  local_60 = 0x7372667965697478;
  local_58 = 0x766f78757a74676c;
  local_50 = 0x6e7372626e64666c;
  local_48 = 0x647368687976726c;
  local_40 = 0x6e786f66727878;
  uStack57 = 0x6c626a;
  setvbuf(stdout,(char *)0x0,2,0);
  printf("Enter the secret password: ");
  __isoc99_scanf(&DAT_00402024);
  local_c = 0;
  sVar2 = strlen((char *)&local_68);
  local_14 = (int)sVar2;
  local_18 = 0x55;
  local_1c = 0x33;
  local_20 = 0xf;
  local_21 = 'a';
  for (; local_c < 3; local_c = local_c + 1) {
    for (local_10 = 0; local_10 < local_14; local_10 = local_10 + 1) {
      local_28 = (local_10 % 0xff >> 1 & local_18) + (local_10 % 0xff & local_18);
      local_2c = ((int)local_28 >> 2 & local_1c) + (local_1c & local_28);
      iVar1 = ((int)local_2c >> 4 & local_20) +
              ((int)local_a8[local_10] - (int)local_21) + (local_20 & local_2c);
      local_a8[local_10] = local_21 + (char)iVar1 + (char)(iVar1 / 0x1a) * -0x1a;
    }
  }
  iVar1 = memcmp(local_a8,&local_68,(long)local_14);
  if (iVar1 == 0) {
    printf("SUCCESS! Here is your flag: %s\n","picoCTF{sample_flag}");
  }
  else {
    puts("FAILED!");
  }
  return 0;
}

小結:

學會 angr 自動分析,以及使用 Ghidra

終於完賽啦!


上一篇
[Day 29] rsa_oracle
系列文
picoCTF30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言